package dk.mirasola.systemtraining.bridgewidgets.client.ui.editor;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.LeafValueEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiConstructor;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.ValueBoxBase;
import com.google.gwt.user.client.ui.Widget;

public class IntegerEditor extends Composite implements LeafValueEditor<Integer> {
    interface IntegerEditorUiBinder extends UiBinder<Widget, IntegerEditor> {
    }

    private static IntegerEditorUiBinder uiBinder = GWT.create(IntegerEditorUiBinder.class);

    @UiField
    TextBox integerBox;
    @UiField(provided = true)
    HorizontalPanel panel;
    @UiField
    Image up;
    @UiField
    Image down;

    private int validatedValue = 0;
    private boolean invalid = false;

    public IntegerEditor() {
        this(Integer.MIN_VALUE, Integer.MAX_VALUE);
    }

    @UiConstructor
    public IntegerEditor(final int minValid, final int maxValid) {
        if (minValid >= maxValid) {
            throw new IllegalArgumentException("min valid integer must less than max valid integer");
        }
        validatedValue = minValid;

        panel = new HorizontalPanel();
        panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

        initWidget(uiBinder.createAndBindUi(this));

        int maxLength = Math.max(String.valueOf(minValid).length(), String.valueOf(maxValid).length());
        integerBox.setMaxLength(maxLength);
        integerBox.setVisibleLength(maxLength);
        integerBox.setAlignment(ValueBoxBase.TextAlignment.RIGHT);

        integerBox.addKeyUpHandler(new KeyUpHandler() {
            @Override
            public void onKeyUp(KeyUpEvent event) {
                try {
                    int val = Integer.valueOf(integerBox.getValue());

                    if (val >= minValid && val <= maxValid) {
                        validatedValue = val;
                        integerBox.removeStyleDependentName("invalid");
                        invalid = false;
                    } else {
                        integerBox.addStyleDependentName("invalid");
                        invalid = true;
                    }
                } catch (NumberFormatException e) {
                    integerBox.addStyleDependentName("invalid");
                    invalid = true;
                }
            }
        });

        up.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (invalid || validatedValue == maxValid) {
                    return;
                }

                validatedValue++;
                integerBox.setValue(String.valueOf(validatedValue));
            }
        });

        down.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (invalid || validatedValue == minValid) {
                    return;
                }

                validatedValue--;
                integerBox.setValue(String.valueOf(validatedValue));
            }
        });
    }

    @Override
    public void setValue(Integer value) {
        if (value == null) {
            throw new NullPointerException();
        }
        integerBox.setValue(value.toString());
        validatedValue = value;
    }

    @Override
    public Integer getValue() {
        return validatedValue;
    }
}
